package com.ronz.linkedlist;

import com.ronz.linkedlist.util.DoubleHeroNode;
import com.ronz.linkedlist.util.HeroNode;

/**
 * @Description 演示双向链表的增、删、改、查。
 *              1. 增加结点
 *              2. 按顺序增加结点
 *              3. 删除结点
 *              4. 更新结点
 *              5. 查询所有结点
 * @Author Ronz
 * @Date 2020/12/24 10:37
 * @Version 1.0
 */
public class No6_DoubleLinkedList {

    public static void main(String[] args) {
        DoubleHeroNode heroNode = new DoubleHeroNode(0, "", "");

        DoubleHeroNode node_1 = new DoubleHeroNode(3, "宋江", "及时雨");
        DoubleHeroNode node_2 = new DoubleHeroNode(4, "卢俊义", "玉麒麟");
        DoubleHeroNode node_3 = new DoubleHeroNode(2, "公孙胜", "入云龙");

        System.out.println("=============增加结点==============");
        insertNode(heroNode, node_1);
        insertNode(heroNode, node_2);
        insertNode(heroNode, node_3);
        showList(heroNode);

        System.out.println("=============删除结点==============");
        deleteNode(heroNode, node_3);
        showList(heroNode);

        System.out.println("=============更新节点==============");
        node_3.name = "公孙圣圣";
        node_3.nickName = "入云龙龙";
        updateNode(heroNode, node_3);
        showList(heroNode);

        System.out.println("=============按顺序增加结点==============");
        heroNode = new DoubleHeroNode(0, "", "");
        DoubleHeroNode node_4 = new DoubleHeroNode(3, "宋江", "及时雨");
        DoubleHeroNode node_5 = new DoubleHeroNode(5, "公孙胜", "入云龙");
        DoubleHeroNode node_6 = new DoubleHeroNode(1, "孙悟空", "齐天大圣");
        insertNodeByOrder(heroNode, node_4);
        insertNodeByOrder(heroNode, node_5);
        insertNodeByOrder(heroNode, node_6);
        showList(heroNode);
    }


    /**
     * @Description 1. 在链表中增加一个结点
     * @Param [head, node]
     * @return void
     */
    public static void insertNode(DoubleHeroNode head, DoubleHeroNode node){
        DoubleHeroNode tempNode = head;
        while (true){
            if (tempNode.next == null){ // 如果到了最后一个结点，那就直接在末尾追加
                tempNode.next = node;
                node.pre = tempNode;
                break;
            }
            tempNode = tempNode.next;
        }
    }

    /**
     * @Description 2. 双向链表按照编号顺序添加结点
     * @Param [head, node]
     * @return void
     */
    public static void insertNodeByOrder(DoubleHeroNode head, DoubleHeroNode node){
        DoubleHeroNode tempNode = head;
        while(true){
            if (tempNode.next == null){ // 如果到了链表末尾，直接添加
                tempNode.next = node;
                node.pre = tempNode;
                break;
            }
            if (tempNode.next.no > node.no){
                // 先建立待插入结点与后一个结点的关系
                node.next = tempNode.next;
                tempNode.next.pre = node;
                // 再建立待插入节点与前一个结点的关系
                tempNode.next = node;
                node.pre = tempNode;
                break;
            }
            tempNode = tempNode.next;
        }
    }

    /**
     * @Description 2. 从双向链表中删除一个结点，删除这里也是和单向链表差距最大的地方
     *              单向链表只能通过待删除节点的前一个节点来删除
     *              双向链表可以通过节点本身来删除
     * @Param [head, node]
     * @return void
     */
    public static void deleteNode(DoubleHeroNode head, DoubleHeroNode node){
        // 先判断是不是为空链表
        DoubleHeroNode tempNode = head.next;
        if (tempNode == null){
            System.out.println("链表为空！无法删除");
            return;
        }
        while (true){
            if (tempNode == null){
                // 如果到了末尾还没有
                System.out.println("链表中不存在该结点！");
                break;
            }
            if (tempNode.no == node.no){
                // 如果找到了，就删除本结点
                // 需要注意的是，若删除最后一个结点，则此结点没有下一个结点，如果不进行判断，会空指针异常
                if (tempNode.next != null){
                    tempNode.next.pre = tempNode.pre;
                }
                tempNode.pre.next = tempNode.next;
                System.out.println("结点已找到，删除成功！");
                break;
            }
            tempNode = tempNode.next;
        }
    }

    /**
     * @Description 3. 更新结点信息
     * @Param [head, node]
     * @return void
     */
    public static void updateNode(DoubleHeroNode head, DoubleHeroNode node){
        // 1. 先判断是不是空链表
        DoubleHeroNode tempNode = head.next;
        if (tempNode == null){
            System.out.println("链表为空！无法更新");
            return;
        }
        while(true){
            if (tempNode == null){
                System.out.println("链表中不存在该结点！");
                break;
            }
            if (tempNode.no == node.no){
                tempNode.name = node.name;
                tempNode.nickName = node.nickName;
                break;
            }
            tempNode = tempNode.next;
        }
    }

    /**
     * @Description 4. 显示所有结点
     * @Param [head]
     * @return void
     */
    public static void showList(DoubleHeroNode head){
        DoubleHeroNode tempNode = head.next;
        if (tempNode == null){
            System.out.println("链表为空！");
        }
        while(true){
            if (tempNode == null){
                break;
            }
            System.out.println(tempNode);
            tempNode = tempNode.next;
        }
    }
}
